/**
 @author 迷途小羔羊
 2015.3.5
 */
namespace GYLite
{
										
		
	export class GYListH extends GYListBase
	{		
		/**水平List组件
		 @inheritDoc*/
		public constructor(size:number,getGridFunc:Function=null, getThisObject:any=null, setGridFunc:Function=null, setThisObject:any=null)
		{
			super(size,getGridFunc,getThisObject,setGridFunc,setThisObject);
		}
		
		protected initComponent():void
		{
			let s = this;
			super.initComponent();			
			var grid:IItemRender;
			if(s._boxs!=0)
			{
				grid=s.getGrid();
				s._settingboxW = s._boxW = grid.width;
				s._settingboxH = s._boxH = grid.height;
				s._itemRatio = s._boxW / s._boxH;
				grid.dispose();
				if(s._boxs > 0)								
					s.width = s._boxs;
				else				
					s.boxs = -s._boxs;
			}			
		}
		public set boxs(val:number)
		{var s=this;
			if(val < 0)return;
			if(val == s._boxs)return;			
			s._boxs = s._virtual_layout?val:(s._dataProvider?s._dataProvider.length:0);
			s.invalidBoxNum();
		}
		public get boxs():number
		{
			let s = this;
			return s._boxs;
		}
		protected boxNumChange(update:boolean=false):void
		{var s=this;
			var i:number,len:number;
			var grid:IItemRender;
			var val:number;
			var w:number;
			var box:number;
			var offset:number;
			val = s.hScroller.position;
			w=s._settingboxW + s._padding;			
			offset = s._virtual_layout?val % w:0;
			len = s._grids.length;
			for(i = update?0:len;i<s._boxs;++i)
			{
				if(i >= len)
				{
					grid=s.getGrid();
					s._grids.push(grid);
					s.addElementAt(grid,0);
				}
				else
				{
					grid = s._grids[i];
					if(grid.parent == null)
						s.addElementAt(grid,0);
				}	
				if(s._dataProvider)
				{
					var ind:number = s._lastBox + i;
					grid.itemIndex = ind;
					s.setGrid(grid,s._dataProvider[ind]);
					grid.x = w * i - offset;
					grid.selected = s._selectedData!=null && grid.getData() == s._selectedData;
				}
				else
					s.setGrid(grid,null);
			}
			len = s._grids.length;
			for(i = 0;i<len;++i)
			{
				grid = s._grids[i];
				if(i < s._boxs)
				{
					if(grid.parent == null)
						s.addElementAt(grid, i);
				}
				else if(grid.parent)
					s.removeElement(grid);
			}
			
		}		
		/**@inheritDoc*/
		public scrollToIndex(val:number):void
		{
			let s = this;
			s.hScroller.position = val * s._settingboxW;
		}
		/**@inheritDoc*/
		public scrollToEndIndex(val:number):void
		{
			let s = this;
			s.hScroller.position = val * s._settingboxW - s._innerWidth + s._settingboxW;
		}
		protected selectLine(data:any,selectedData:any,ctrlKey:boolean,checkNext:boolean=false):void
		{
			let s = this;
			var ind:number=0,stInd:number=0,endInd:number=0;
			var tempData:any;
			var i:number=0,len:number=0;
			var tempVec:any[];
			var tempItem:IItemRender;
			var end:number=0;
			var flag:number=0,mX:number = s.mouseX;
			if(checkNext)
			{
				tempItem = s._dataToItemDict.getValue(data);
				if(tempItem == null)
				{
					if(mX > s.width)
						flag = 1;
					else if(mX < 0)
						flag = -1;
				}
				else
				{
					if(mX > tempItem.x + tempItem.width)
						flag = 1;
					else if(mX < tempItem.x)
						flag = -1;	
				}
				if(flag == 0)
					return;
			}
			else
				s._nextData = data;
			stInd = s._dataProvider.indexOf(selectedData);
			endInd = s._dataProvider.indexOf(data);
			if(flag != 0)
			{
				if(flag == 1)
				{
					endInd = endInd < s._dataProvider.length - 1? endInd + 1: s._dataProvider.length - 1;
					data = s._dataProvider[endInd];
				}
				else if(flag == -1)
				{
					endInd = endInd > 0? endInd - 1: endInd;
					data = s._dataProvider[endInd];
				}
				if(mX > s.width || mX < 0)
					s.scrollToEndIndex(endInd);
			}
			s._nextData = data;
			if(endInd < stInd)
			{
				ind = endInd;
				endInd = stInd;
				stInd = ind;
			}
			len = endInd + 1;
			end = s._selectList.length-1;
			for(i=stInd;i<len;++i)
			{
				tempData = s._dataProvider[i];
				ind = s._selectList.indexOf(tempData);
				if(ind == -1)
				{
					if(s._selectList.length >= s._canSelectNum)
						continue;
					if(tempData)
					{
						tempItem = s._dataToItemDict.getValue(tempData);
						s._selectList.push(tempData);
						if(tempItem)
							tempItem.selected = true;
					}
				}
				else if(!ctrlKey)
				{
					tempData = s._selectList[end];
					s._selectList[end] = s._selectList[ind];
					s._selectList[ind]= tempData;
					--end;
				}
			}
			if(!ctrlKey && end > -1)
			{
				tempVec = s._selectList.splice(0,end + 1);
				len = tempVec.length;
				while(--len>-1)
				{
					tempItem = s._dataToItemDict.getValue(tempVec[len]);
					if(tempItem)
					{
						tempItem.selected = false;
					}
				}
			}
			if(s.hasEventListener(GYViewEvent.SELECTED) && s._mouseSelect)
			{
				s.dispatchEvent(new GYViewEvent(GYViewEvent.SELECTED));
				s._mouseSelect = false;
			}
		}
		public updateGrid():void
		{
			let s = this;
			var i:number;
			var grid:IItemRender;
			var w:number, baseWidth:number;
			baseWidth = s.baseWidth;
			w=s._settingboxW + s._padding;
			s._max = s._dataProvider?Math.max(s._dataProvider.length * w - s._padding,baseWidth):s.baseWidth;
			s.hScroller.maximum = s._max-baseWidth + s._scrollPadLeft + s._scrollPadRight;
			s.hScroller.barPercent = baseWidth/s._max;
			for(i=0;i<s._boxs;++i)
			{
				grid=s._grids[i];
				grid.width = s._settingboxW;
				grid.height = s._settingboxH;
			}
			if(s.hScroller.value > s.hScroller.maximum)
				s.hScroller.value = s.hScroller.maximum;
			s.hScrollChange();
		}
		/**@inheritDoc*/
		public get dataProvider():Array<any>
		{
			let s = this;
			return s._dataProvider;
		}
		public set dataProvider(val:Array<any>)
		{
			let s = this;
			var w:number=s._settingboxW + s._padding;			
			if(!s._keepSelected)
			{
				s._selectedData = null;
				s._selectIndex = -1;
				if(s._canSelectNum > 1)
					s._selectList.length = 0;
			}
			s._dataProvider=(val?val:[]);
			if(!s._virtual_layout)
			{
				s._boxs = s._dataProvider.length;
				if(!s._boxNumUpdate)
					s.boxNumChange(true);
			}
			if(s._boxNumUpdate)
				s._boxNumUpdateReset = true;
			s._max = Math.max(s._dataProvider.length * w - s._padding,s.baseWidth);
			s.hScroller.maximum=s._max-s.baseWidth + s._scrollPadLeft + s._scrollPadRight;
			s.hScroller.barPercent=s.baseWidth/s._max;
			if(s.hScroller.position > s.hScroller.maximum)
				s.hScroller.position = s.hScroller.maximum;
			s.scrollerPolicy = s._scrollerPolicy;
			s.hScrollChange(null,true);
		}
		protected hScrollChange(e:GYScrollerEvent=null, update:boolean = false, updatePos:boolean = true)
		{
			let s = this;
			if(s._dataProvider==null)
				return;
			if(s._boxNumUpdate)
				return;
			var val:number;
			var w:number;
			var box:number;
			var offset:number;
			var i:number;
			var grid:IItemRender;
			var nowBox:number;
			val = s.hScroller.position;
			if(!s._virtual_layout)
			{
				s.clipX = val;
				return;
			}
			w=s._settingboxW + s._padding;
			offset=val % w;
			nowBox=(val / w >> 0);			
			box = 0;
			if(!update)
			{
				box=s._lastBox-nowBox;
				if(box < 0)
				{
					if(-box<s._boxs)
					{
						for(i=0;i<-box;++i)
						{
							grid=s._grids.shift();
							s._grids.push(grid);
						}
					}
				}
				else if(box > 0)
				{
					if(box<s._boxs)
					{
						for(i=0;i<box;++i)
						{
							grid=s._grids.pop();
							s._grids.unshift(grid);
						}
					}
				}
			}
			var tempLine:number= s._boxs + box - 1;
			for(i=0;i<s._boxs;++i)
			{
				grid = s._grids[i];
				var ind:number = nowBox + i;
				grid.itemIndex = ind;
				if(box > 0 && i < box || box < 0 && i > tempLine || update)
					s.setGrid(grid,s._dataProvider[ind]);
				if(updatePos)
					grid.x = w * i - offset;
			}
			s._lastBox = nowBox;
		}
		/**刷新列表可见的所有项*/		
		public updateItems():void
		{
			let s = this;
			s.hScrollChange(null,true, false);
		}
		protected wheelRoll(e):void
		{
			let s = this;			
			if(!s._wheelScroll)return;
			if(s._isDragging && s.dragForbiddenWheel)return;
			var val:number;
			val = s._wheelStep == 0?s._settingboxW:s._wheelStep;			
			s.hScroller.setPosition(s.hScroller.position+(e.deltaY > 0?val:-val),true);
		}
		public set_height(val:number):boolean
		{
			let s = this;			
			let flag:boolean = super.set_height(val);			
			s._innerHeight = val - (s.hScroller.parent?s.hScroller.height:0);
			s.autoItemSize = s._autoItemSize;
			return flag;
		}		
		public set_width(val:number):boolean
		{
			let s = this;						
			let flag:boolean;
			flag = super.set_width(val);
			s._innerWidth = s.hScroller.width = val;
			var w:number = s.baseWidth;						
			s._max = s._dataProvider?Math.max(s._dataProvider.length * (s._settingboxW + s._padding) - s._padding,w):w;
			s.hScroller.maximum = s._max - w + s._scrollPadLeft + s._scrollPadRight;
			s.hScroller.barPercent = w/s._max;
			s.scrollerPolicy = s._scrollerPolicy;
			s.boxs = (s._settingboxW + s._padding < s._innerWidth)?(Math.ceil(s._innerWidth / (s._settingboxW + s._padding)) + 1):1;
			return flag;
		}		
		public set autoItemSize(val:number)
		{
			let s = this;			
			s._autoItemSize = val;
			if(s._autoItemSize > 0)
			{
				s.setBoxHeight(s._innerHeight);
				if(s._autoItemSize == 2 && s._itemRatio == s._itemRatio)
					s.setBoxWidth(s._innerHeight * s._itemRatio);
				else if(s._autoItemSize == 1 && s._itemCount == s._itemCount)
					s.setBoxWidth(Math.floor(s._innerWidth / s._itemCount));
			}	
			else
			{
				s.setBoxWidth(s._boxW);
				s.setBoxHeight(s._boxH);
			}			
		}
		/**列表项非滚动方向自动适应组件尺寸,0不适应 1item朝非滚动方向拉伸适应 2item等比适应*/
		public get autoItemSize():number
		{
			return this._autoItemSize;
		}
		/**滚动条 0自动 1显示 2不显示*/
		public get scrollerPolicy():number
		{
			let s = this;
			return s._scrollerPolicy;
		}
		public set scrollerPolicy(val:number)
		{
			let s = this;
			s._scrollerPolicy=val;
			var show:boolean;
			if(s._scrollerPolicy == 0)
			{
				if(s.hScroller.barPercent < 1)
					show = true;
				else
					show = false;
			}
			else if(s._scrollerPolicy == 1)
				show = true;
			else
				show = false;
			if(show)
			{
				if(s.hScroller.parent == null)
				{
					s.baseAdd(s.hScroller);
					s.set_height(s.$height);					
				}					
			}
			else
			{
				if(s.hScroller.parent)
				{
					s.baseRemove(s.hScroller);
					s.set_height(s.$height);					
				}
			}
		}
		
		protected downGroup(e:egret.TouchEvent)
		{
			let s = this;
			if(s.mouseY >= s.hScroller.y && s.mouseY <= s.hScroller.y + s.hScroller.height)
				return;
			s._touchId = e.touchPointID;
			if(GYSprite.pushGlobalDrag(this))
				s.groupDrag();
			else
				s.addEventListener(GYEvent.GLOABL_DRAG, s.globalDragCall,s);
		}
		protected dragLoop(t:number):void
		{
			let s = this;
			var mX:number;
			let nt:number;
			let frameParam:number;
			let xFlag:boolean;
			let temp:number;
			nt = Date.now();
			frameParam = 1000/egret.ticker.$frameRate|0;			
			xFlag = s._moveXTime < 100;			
			s._moveXTime = xFlag?s._moveXTime + Math.min(frameParam,nt - s._lastXDragTime):Math.min(frameParam,nt - s._lastXDragTime);
			mX = s.mouseX - s._clipRect.x;			
			s._lastYDragTime = s._lastXDragTime = nt;
			if(mX > s.tempX && !s._dragPreEnabled)return;
			if(mX < s.tempX && !s._dragNextEnabled)return;				
			temp = s.tempX - mX;
			if(s._dragLock || Math.abs(temp) > s.dragValue)
			{
				s._isDragging = true;
				s.dragLock = true;
				s.easeSpeedX = xFlag?s.easeSpeedX+temp:temp;
				s.hScroller.position += temp;
				s.tempX = mX;				
				if(s.hScroller.position == 0 && s.easeSpeedX < 0 || s.hScroller.position == s.hScroller.maximum && s.easeSpeedX > 0)
				{
					if(GYSprite.shiftGlobalDrag(2))
						s.clearGlobalDrag();
				}
			}
			else if(GYLite.GYSprite.hasGlobalVDrag())
			{
				let dragMoveY:boolean;
				var mY:number = s.mouseY - s._clipRect.y;
				dragMoveY = Math.abs(s.tempY - mY) > s.dragValue;
				s.tempY = mY;
                if(dragMoveY)
					++GYLite.GYSprite.globalVDrag;
                if(GYLite.GYSprite.globalVDrag > GYLite.GYSprite.globalVDragCount)
                {
                    if (GYLite.GYSprite.shiftGlobalDrag(2))
                        s.clearGlobalDrag();
                }
			}
		}
		protected groupDrag():void
		{
			let s = this;
			if(s.hScroller.tween)
				s.dragLock = true;
			s.hScroller.stopScroll();			
			GYSprite.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,s.touchMove,s);
			s._lastYDragTime = s._lastXDragTime = Date.now();
			s.tempX = this.mouseX - s._clipRect.x;
			s._moveXTime = s.easeSpeedX = 0;
			s._scrollToPos = NaN;
			GYSprite.addStageDown(s,s.upGroup, s);		
			this.addEventListener(egret.TouchEvent.TOUCH_END, s.upGroup, s);
		}		
		protected groupDragStop():void
		{
			let s = this;
			if(s.tempX != s.tempX)return;
			s._isDragging = false;			
			GYSprite.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE,s.touchMove,s);
			let dis:number,minDis:number;
			let temp:number,tarPos:number,addDis:number;
			let frameParam:number;
			frameParam = 1000/egret.ticker.$frameRate;
			s.removeEventListener(egret.TouchEvent.TOUCH_END, s.upGroup, s);			
			let nt:number = Date.now();			
			let dt:number = s._moveXTime;
			let spd:number;
			if(dt > 0 && nt - s._lastXDragTime < s._easeTriggerTime && (s.easeSpeedX > s.easeValue || s.easeSpeedX < -s.easeValue))
			{
				spd = s.easeSpeedX / dt * frameParam * s.speedParam;	
				dis = (s.hScroller.limitMax == s.hScroller.limitMax && s.hScroller.limitMax < s.hScroller.maximum)?s.hScroller.limitMax:s.hScroller.maximum;
				minDis = (s.hScroller.limitMin == s.hScroller.limitMin && s.hScroller.limitMin > 0)?s.hScroller.limitMin:0;
				addDis = Math.abs(spd) * spd * s._easeSpeedValue;
				temp = s.hScroller.position + addDis;
				if(temp < minDis)
				{
					tarPos = minDis;
					addDis = (tarPos - s.hScroller.position);
				}						
				else if(temp > dis)
				{
					tarPos = dis;
					addDis = tarPos - s.hScroller.position;
				}
				else
				{
					tarPos = temp;					
				}
				s.hScroller.scrollToPosition(tarPos, (temp < minDis || temp > dis)?s._easeTime: Math.abs(addDis / spd * frameParam * 2));				
			}
			else if(s._scrollPosLimit == s._scrollPosLimit)
			{
				s.scrollEnd();
			}
			s.tempX = NaN;
			s.dragLock = false;
		}

		public scrollToNextItem():number
		{let s =this;			
			let pos:number;
			let pad:number;
			let nextPos:number;
			if(!s._overlying)
			{				
				if(s.hScroller.tween)return;
			}
			nextPos = s._scrollToPos == s._scrollToPos?s._scrollToPos:s.hScroller.position;
            if(nextPos > s.hScroller.maximum)return;
			pad = s._scrollPosLimit == s._scrollPosLimit?s._scrollPosLimit:(s._settingboxW + s._padding);
			pos = ((nextPos / pad >> 0) + 1) * pad;
			pos = pos > s.hScroller.limitMax?s.hScroller.limitMax:(pos > s.hScroller.maximum?s.hScroller.maximum:pos);
			s.hScroller.scrollToPosition(pos, s.scrollNextTime == s.scrollNextTime?s.scrollNextTime:pad);
			s._scrollToPos = pos;
			return pos;
		}		
		public scrollToPreItem():number
		{let s =this;
			let pos:number;
			let pad:number;
			var nextPos:number;
			if(!s._overlying)
			{				
				if(s.hScroller.tween)return;
			}	
			nextPos = s._scrollToPos == s._scrollToPos?s._scrollToPos:s.hScroller.position;
            if(nextPos < 0)return;		
			pad = s._scrollPosLimit == s._scrollPosLimit?s._scrollPosLimit:(s._settingboxW + s._padding);
			if(nextPos % pad == 0)
				pos = ((nextPos / pad >> 0) - 1) * pad;
			else	
				pos = ((nextPos / pad >> 0) * pad);
			pos = pos < s.hScroller.limitMin?s.hScroller.limitMin:(pos < 0?0:pos);
			s.hScroller.scrollToPosition(pos, s.scrollNextTime == s.scrollNextTime?s.scrollNextTime:pad);
			s._scrollToPos = pos;
			return pos;
		}
		protected scrollEnd(e:GYScrollerEvent=null):void
		{let s =this;
			if(s._scrollPosLimit != s._scrollPosLimit)return;
			if(s._scrollToPos != s._scrollToPos || s._scrollToPos == s._scrollToPos && Math.abs(s._scrollToPos - s.hScroller.position) > 1)
			{
				s._scrollToPos = NaN;
				if(s.easeSpeedX > 0)
					s.scrollToNextItem();
				else if(s.easeSpeedX < 0)
					s.scrollToPreItem();
				else
				{
					let offset:number;
					offset = s.hScroller.position % s.scrollPosLimit;
					if(offset > 0)
					{
						if(offset > s.scrollPosLimit / 2)
						{
							s.scrollToNextItem();
						}
						else
						{
							s.scrollToPreItem();
						}
					}				
				}
				s.easeSpeedX = 0;
			}
			else
				s._scrollToPos = NaN;		
		}
		public clone():GYListBase
		{
			let s = this;
			let list:GYListH;
			list = new GYListH(s._boxs, s.createGrid, s, s.setGrid, s);
			list.copy(s);
			return list;
		}
		public copy(list:GYListH):void
		{
			let s = this;
			if(list == null)return;
			s.width = list.width;
			s.height = list.height;
			s.dataProvider = list.dataProvider;
			s.canSelectNum = list.canSelectNum;
			s.scrollerPolicy = list.scrollerPolicy;
			s.keepSelected = list.keepSelected;
			s.dragSelect = list.dragSelect;
			s.virtual_layout = list.virtual_layout;
			s.overlying = list.overlying;
			s.wheelStep = list.wheelStep;
			s.wheelScroll = list.wheelScroll;
			s.selectInterval = list.selectInterval;
			
			s.hScroller.x = list.hScroller.x;
			s.hScroller.y = list.hScroller.y;
			s.hScroller.width = list.hScroller.width;
			s.hScroller.height = list.hScroller.height;
			s.selectedData = list.selectedData;
		}
	}
}